package com.bike.bikeserver.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bike.bikeserver.common.core.domain.CommonResult;
import com.bike.bikeserver.common.enums.UserKey;
import com.bike.bikeserver.common.utils.MD5Utils;
import com.bike.bikeserver.common.utils.MailUtils;
import com.bike.bikeserver.common.utils.TokenUtils;
import com.bike.bikeserver.domain.SysRole;
import com.bike.bikeserver.domain.User;
import com.bike.bikeserver.domain.vo.UserDeleteVo;
import com.bike.bikeserver.domain.vo.UserRegisterVo;
import com.bike.bikeserver.mapper.SysRoleMapper;
import com.bike.bikeserver.mapper.UserMapper;
import com.bike.bikeserver.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import static com.bike.bikeserver.constant.Constants.*;

/**
 * @version 1.0
 * @Author ZZX
 * @Date 2023/7/16 15:24
 */
@Service
@Slf4j
public class UserServiceImpl implements IUserService
{
    @Autowired
    UserMapper userMapper;
    @Autowired
    SysRoleMapper sysRoleMapper;
    @Autowired
    TokenUtils tokenUtils;
    @Autowired
    private MailUtils mailUtils;
    @Value("${zcbike.name}")
    private String text;

    @Override
    public CommonResult getCode(UserRegisterVo userRegisterVo)
    {
        // 检查是否已存在该邮箱的验证码，防止重复发送，浪费资源
        String preCode = tokenUtils.getToken(userRegisterVo.getEmail());
        if (preCode != null)
        {
            return CommonResult.warn("验证码尚未过期，请输入已获得的验证码！");
        }
        // 发送邮箱验证码
        String code = mailUtils.verifyCode(6);
        boolean isSuccess = mailUtils.sendTextMailMessage(userRegisterVo.getEmail(), "账号注册或密码找回：" + text, "[" + text + "]用户验证码：" + code + "（5分钟内有效）。为确保信息安全，请勿向他人透露。");
        if (!isSuccess)
        {
            return CommonResult.warn("此邮箱不存在，请更换已注册的邮箱！");
        }
        // 保存邮箱验证码
        tokenUtils.saveToken(userRegisterVo.getEmail(), code, EMAIL_CODE_TIMEOUT);
        return CommonResult.success("获取验证码成功");
    }

    @Override
    public CommonResult userRegister(UserRegisterVo userRegisterVo)
    {
        // 检验验证码是否过期或正确（根据邮箱获取redis中的值）
        String code = tokenUtils.getToken(userRegisterVo.getEmail());
        if (code == null)
        {
            return CommonResult.warn("验证码已失效，请重新获取！");
        }
        if (!userRegisterVo.getCode().equals(code))
        {
            return CommonResult.warn("验证码输入错误，请核对重试！");
        }
        // 根据用户名检查用户是否存在
        LambdaQueryWrapper<User> user_wrapper = new LambdaQueryWrapper<>();
        user_wrapper.eq(User::getUserName, userRegisterVo.getUserName());
        User user = userMapper.selectOne(user_wrapper);
        // 如果已存在，返回错误提示
        if (user != null)
        {
            return CommonResult.warn("用户已注册，请直接登录！");
        }
        // 如果不存在，判断邮箱是否已经存在，加盐入库后，返回注册成功提示
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUserEmail, userRegisterVo.getEmail());
        User one = userMapper.selectOne(wrapper);
        // 如果邮箱已存在，提示更换邮箱
        if (one != null)
        {
            return CommonResult.warn("邮箱已被用于注册另一个账号，请更换邮箱！");
        }
        // 如果邮箱不存在，加盐入库
        User newUser = new User();
        newUser.setUserName(userRegisterVo.getUserName());
        // 默认常规用户
        newUser.setUserType(BACK_USER_LOOK);
        newUser.setAccount(userRegisterVo.getAccount());
        newUser.setUserEmail(userRegisterVo.getEmail());
        // 加盐
        String salt = MD5Utils.getSalt();
        newUser.setLoginSalt(salt);
        newUser.setPwd(MD5Utils.encode(salt + userRegisterVo.getPwd()));
        userMapper.insert(newUser);
        // 将用户加入权限表
        SysRole sysRole = new SysRole();
        sysRole.setUserSource(UserKey.BEHIND.getValue());
        sysRole.setUserKey(newUser.getAccount());
        sysRole.setUserType(newUser.getUserType());
        sysRole.setUserRight(USER_RIGHT_LOOK);
        sysRoleMapper.insert(sysRole);
        return CommonResult.success("注册成功，可返回登录！");
    }

    @Override
    public CommonResult userLogin(String account, String pwd)
    {
        // 从数据库查找是否存在用户
        LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(User::getAccount, account);
        User user = userMapper.selectOne(userWrapper);
        // 如果存在，返回用户信息和token，否则返回错误提示
        if (user != null)
        {
            // 判断密码是否正确（加盐后）
            String loginSalt = user.getLoginSalt();
            String loginPwd = MD5Utils.encode(loginSalt + pwd);
            if (!loginPwd.equals(user.getPwd()))
            {
                return CommonResult.warn("密码错误，请重试！");
            }
            // 调用sa-token的登录方法
            // 会话登录：参数填写要登录的账号id，建议的数据类型：long | int | String， 不可以传入复杂类型，如：User、Admin 等等
            StpUtil.login(BACK_USER_PREFIX + user.getId());
            log.info("后台管理系统：用户【" + user.getUserName() + "】于" + new Date() + "登录成功！");
            // 查看当前redis
            System.out.println(tokenUtils.getAllKeyValues());
            return CommonResult.success("登录成功", new HashMap<String, String>()
            {{
                put("userId", user.getId().toString());
                put("userName", user.getUserName());
                put("token", StpUtil.getTokenValue());
            }});
        } else
        {
            return CommonResult.warn("登录失败！此用户不存在！");
        }
    }

    @Override
    public CommonResult userLogout(Integer userId)
    {
        // 当前会话注销登录
        StpUtil.logout(BACK_USER_PREFIX + userId);
        User user = userMapper.selectById(userId);
        log.info("后台管理系统：用户【" + user.getUserName() + "】于" + new Date() + "退出登录！");
        return CommonResult.success();
    }

    @Override
    public CommonResult findPwd(UserRegisterVo userRegisterVo)
    {
        // 检验验证码是否过期或正确（根据邮箱获取redis中的值）
        String code = tokenUtils.getToken(userRegisterVo.getEmail());
        if (code == null)
        {
            return CommonResult.warn("验证码已失效，请重新获取！");
        }
        if (!userRegisterVo.getCode().equals(code))
        {
            return CommonResult.warn("验证码输入错误，请核对重试！");
        }
        // 根据用户名检查用户是否存在
        LambdaQueryWrapper<User> user_wrapper = new LambdaQueryWrapper<>();
        user_wrapper.eq(User::getAccount, userRegisterVo.getAccount());
        User user = userMapper.selectOne(user_wrapper);
        // 如果不存在返回错误提示
        if (user == null)
        {
            return CommonResult.warn("该账号不存在！请更改");
        }
        // 判断邮箱是否一致
        if (!userRegisterVo.getEmail().equals(user.getUserEmail()))
        {
            return CommonResult.warn("输入邮箱与绑定邮箱不一致！请更改");
        }
        // 如果存在，更新数据库（依旧用加盐的方式），返回成功信息
        user.setPwd(MD5Utils.encode(user.getLoginSalt() + userRegisterVo.getPwd()));
        return CommonResult.success("密码修改成功！可前去登录！");
    }

    @Override
    public CommonResult deleteAccount(UserDeleteVo userDeleteVo)
    {
        // 检查Account是否为root，如果是root，就不能删除，因为这是最高权限账号，删了就坏事了
        if (BACK_USER_ROOT.equals(userDeleteVo.getUserName()))
        {
            return CommonResult.warn("账号注销失败！root用户不可注销！");
        }
        // 同时删除用户权限里的角色
        User user = userMapper.selectById(userDeleteVo.getUserId());
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRole::getUserKey, user.getAccount());
        wrapper.eq(SysRole::getUserSource, UserKey.BEHIND.getValue());
        SysRole sysRole = sysRoleMapper.selectOne(wrapper);
        sysRoleMapper.deleteById(sysRole.getId());
        userMapper.deleteById(userDeleteVo.getUserId());
        return CommonResult.success("注销成功！即将退出登录！");
    }
}